import { Bluetooth } from './index';
/**
 * 微信蓝牙错误处理中心
 * 功能：错误分类、自动恢复、策略配置、错误上报
 */
type BluetoothError = TaroGeneral.BluetoothError | Error;
type StandError = {
  code: number;
  message: string;
  stack?: string;
  raw: BluetoothError | Error;
};
type ErrorMatch = (error: StandError) => boolean;
type ErrorHandler = {
  handler: (context: Record<string, any>) => Promise<any>;
  options: { delay?: number; maxAttempts?: number };
};

export class BluetoothErrorHandler {
  public bluetooth: Bluetooth;
  private _recoveryStrategies: Map<ErrorMatch, ErrorHandler>;
  constructor(bluetooth: Bluetooth) {
    this.bluetooth = bluetooth;
    this._recoveryStrategies = new Map();
  }
  /**
   * 添加自定义错误处理策略
   * */
  addStrategy(
    matcher: ErrorMatch,
    handler: ErrorHandler['handler'],
    options: ErrorHandler['options'] = {
      delay: 0,
      maxAttempts: 0
    }
  ) {
    this._recoveryStrategies.set(matcher, { handler, options });
  }

  /**
   * 执行错误处理
   */
  async handle(error: BluetoothError, context: Record<string, any> = {}) {
    const err = this._normalizeError(error);
    const strategy = this._findMatchingStrategy(err);
    this._reportError(err);
    if (!strategy) {
      return;
    }
    // 执行恢复策略
    try {
      const { handler, options } = strategy;
      return this._executeWithRetry(() => handler({ ...context, error: err }), options);
    } catch (recoveryError) {
      this._reportError({
        code: -1,
        message: `recoveryError:${recoveryError.message}`,
        stack: recoveryError.stack,
        raw: recoveryError
      });
    }
  }

  // 错误标准化
  _normalizeError(error: BluetoothError): StandError {
    if (error instanceof Error) {
      return {
        code: -1,
        message: error.message,
        stack: error.stack,
        raw: error
      };
    } else {
      return {
        code: error.errCode,
        message: error.errMsg || '未知蓝牙错误',
        stack: new Error().stack,
        raw: error
      };
    }
  }

  // 查找匹配策略
  _findMatchingStrategy(error: StandError) {
    for (const [matcher, strategy] of this._recoveryStrategies) {
      if (matcher(error)) return strategy;
    }
    return null;
  }

  // 带重试的执行
  async _executeWithRetry(fn: () => Promise<void>, options: ErrorHandler['options'] = {}) {
    let attempt = 0;
    const maxAttempts = options.maxAttempts || 1;
    const delay = options.delay || 0;
    while (attempt < maxAttempts) {
      try {
        attempt++;
        return await fn();
      } catch (err) {
        if (attempt >= maxAttempts) throw err;
        if (delay > 0) await new Promise((r) => setTimeout(r, delay));
      }
    }
  }
  // 错误上报
  _reportError(error: StandError) {
    console.log('[BLE Error]', error);
  }
}

export function createErrorHandler(bluetooth: Bluetooth) {
  const handler = new BluetoothErrorHandler(bluetooth);
  // 连接超时自动重试
  handler.addStrategy(
    (err) => err.code === 10004,
    async () => {
      await bluetooth.disconnect();
      const { deviceId } = bluetooth.getState();
      return bluetooth.connect(deviceId);
    },
    { maxAttempts: 2 }
  );

  // // 蓝牙未启用引导用户
  // handler.addStrategy(
  //   (err) => err.code === 10001,
  //   () => {
  //     wx.showModal({
  //       title: '蓝牙未开启',
  //       content: '请前往设置打开蓝牙',
  //       showCancel: false
  //     });
  //     return Promise.reject(err); // 不自动恢复
  //   }
  // );
  return handler;
}
